//
//  UIScrollView+Empty.swift
//  Exchange
//
//  Created by 孟祥群 on 2018/8/2.
//  Copyright © 2018年 common. All rights reserved.
//

import UIKit

extension UIScrollView {
    struct RuntimeKey {
        static let kEmptyViewKey = UnsafeRawPointer.init(bitPattern: "kEmptyViewKey".hashValue)
    }
    
    public var cy_emptyView: CyEmptyView? {
        set {
            objc_setAssociatedObject(self, RuntimeKey.kEmptyViewKey!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            for view in self.subviews {
                if view.isKind(of: CyEmptyView.classForCoder()) {
                    view.removeFromSuperview()
                }
            }
            self.addSubview(cy_emptyView!)
            self.cy_emptyView?.isHidden = true
        }
        get {
            return objc_getAssociatedObject(self, RuntimeKey.kEmptyViewKey!) as? CyEmptyView
        }
    }
    
    //MAKR: --- 根据 DataSource 判断是否自动显示 emptyView
    public func cy_startLoading() {
        self.cy_emptyView?.isHidden = true
    }
    
    public func cy_endLoading() {
        
    }
    
    //手动控制显隐方法，不受DataSource的影响，需要把 autoShowEmptyView = false
    public func cy_showEmptyView() {
        self.cy_emptyView?.superview?.layoutSubviews()
        self.cy_emptyView?.isHidden = false
        //始终保持显示在最上层
        if self.cy_emptyView != nil {
            self.bringSubview(toFront: self.cy_emptyView!)
        }
    }
    
    public func cy_hideEmptyView() {
        self.cy_emptyView?.isHidden = true
    }
    
    //MARK: - Private Method
    fileprivate func totalDataCount() -> NSInteger {
        var totalCount: NSInteger = 0
        if self.isKind(of: UITableView.classForCoder()) {
            let tableView = self as? UITableView
            if (tableView?.numberOfSections)! >= 1 {
                for section in 0...(tableView?.numberOfSections)!-1 {
                    totalCount += (tableView?.numberOfRows(inSection: section))!
                }
            }
        }
        else if self.isKind(of: UICollectionView.classForCoder()) {
            let collectionView = self as? UICollectionView
            if (collectionView?.numberOfSections)! >= 1 {
                for section in 0...(collectionView?.numberOfSections)!-1 {
                    totalCount += (collectionView?.numberOfItems(inSection: section))!
                }
            }
        }
        return totalCount
    }
    
    
    fileprivate func getDataAndSet() {
        if self.totalDataCount() == 0 {
            show()
        } else {
            hide()
        }
    }
    
    fileprivate func show() {
        if self.cy_emptyView?.autoShowEmptyView == false {
            self.cy_emptyView?.isHidden = true
            return
        }
        cy_showEmptyView()
    }
    
    fileprivate func hide() {
        if self.cy_emptyView?.autoShowEmptyView == false {
            self.cy_emptyView?.isHidden = true
            return
        }
        cy_hideEmptyView()
    }
}

extension UITableView:SelfAware {
    static func awake() {
        UITableView.classInit()
    }
    
    static func classInit() {
        swizzleMethod
    }
    private static let swizzleMethod: Void = {
        //insertSections
        let originalSelector = #selector(insertSections(_:with:))
        let swizzledSelector = #selector(cy_insertSections(_:with:))
        CYRunTime.exchangeMethod(selector: originalSelector, replace: swizzledSelector, class: UITableView.self)
        
        //deleteSections
        let originalSelector1 = #selector(deleteSections(_:with:))
        let swizzledSelector1 = #selector(cy_deleteSections(_:with:))
        CYRunTime.exchangeMethod(selector: originalSelector1, replace: swizzledSelector1, class: UITableView.self)
        
        //insertRows
        let originalSelector2 = #selector(insertRows(at:with:))
        let swizzledSelector2 = #selector(cy_insertRowsAtIndexPaths(at:with:))
        CYRunTime.exchangeMethod(selector: originalSelector2, replace: swizzledSelector2, class: UITableView.self)
        
        //deleteRows
        let originalSelector3 = #selector(deleteRows(at:with:))
        let swizzledSelector3 = #selector(cy_deleteRowsAtIndexPaths(at:with:))
        CYRunTime.exchangeMethod(selector: originalSelector3, replace: swizzledSelector3, class: UITableView.self)
        
        //reload
        let originalSelector4 = #selector(reloadData)
        let swizzledSelector4 = #selector(cy_reloadData)
        CYRunTime.exchangeMethod(selector: originalSelector4, replace: swizzledSelector4, class: UITableView.self)
        
    }()
    
    //section
    @objc  func cy_insertSections(_ sections: NSIndexSet, with animation: UITableViewRowAnimation) {
        cy_insertSections(sections, with: animation)
        getDataAndSet()
    }
    
    @objc  func cy_deleteSections(_ sections: NSIndexSet, with animation: UITableViewRowAnimation) {
        cy_deleteSections(sections, with: animation)
        getDataAndSet()
    }
    
    //row
    @objc  func cy_insertRowsAtIndexPaths(at indexPaths: [IndexPath], with animation: UITableViewRowAnimation){
        cy_insertRowsAtIndexPaths(at: indexPaths, with: animation)
        getDataAndSet()
    }
    
    @objc func cy_deleteRowsAtIndexPaths(at indexPaths: [IndexPath], with animation: UITableViewRowAnimation){
        cy_deleteRowsAtIndexPaths(at: indexPaths, with: animation)
        getDataAndSet()
    }
    
    //reloadData
    @objc func cy_reloadData() {
        self.cy_reloadData()
        self.getDataAndSet()
    }
    
    func creatEmptyView(offset:CGFloat = 0)  {
        let emptyView: EmptyView = EmptyView()
        emptyView.message = kText("暂无相关数据")
        emptyView.frame = self.bounds
        //空数据界面显示
        let emptyV:CyEmptyView = CyEmptyView.emptyViewWithCustomView(customView: emptyView) as! CyEmptyView
        self.cy_emptyView = emptyV
        self.cy_showEmptyView()
    }

    
}



// MARK:- SelfAware 定义协议，使得程序在初始化的时候，将遵循该协议的类做了方法交换
protocol SelfAware: class {
    static func awake()
}

class NothingToSeeHere {
    static func harmlessFunction() {
        let typeCount = Int(objc_getClassList(nil, 0))
        let types = UnsafeMutablePointer<AnyClass>.allocate(capacity: typeCount)
        let autoreleasingTypes = AutoreleasingUnsafeMutablePointer<AnyClass>(types)
        objc_getClassList(autoreleasingTypes, Int32(typeCount))
        for index in 0 ..< typeCount {
            (types[index] as? SelfAware.Type)?.awake()
        }
        //types.deallocate(capacity: typeCount)
        types.deallocate()
    }
}

extension UIApplication {
    private static let runOnce: Void = {
        NothingToSeeHere.harmlessFunction()
    }()
    
    override open var next: UIResponder? {
        // Called before applicationDidFinishLaunching
        UIApplication.runOnce
        return super.next
    }
}
